﻿////////////////////////////////////////////////////////////////////////////////////////////////////
//
// VSCoverageToEmma - Visual Studio Coverage file to Emma converter
// Copyright (c) Kouji Matsui, All rights reserved.
//
// * Redistribution and use in source and binary forms, with or without modification,
//   are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
////////////////////////////////////////////////////////////////////////////////////////////////////

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.IO;
using System.Linq;
using System.Resources;
using System.Reflection;
using System.Collections.Generic;
using System;

namespace VSCoverageToEmma
{
	public sealed class VSCoverageToEmma : Task
	{
		public VSCoverageToEmma()
        {
        }

		[Required]
		public string ConverterName
		{
			get;
			set;
		}

        [Required]
        public ITaskItem VSCoverageFolderPath
		{
			get;
			set;
		}

		public ITaskItem BinariesFolderPath
		{
			get;
			set;
		}

        public ITaskItem SymbolsFolderPath
		{
			get;
			set;
		}

        public ITaskItem EmmaFolderPath
		{
			get;
			set;
		}

		public bool Verbose
		{
			get;
			set;
		}

		[Output]
		public ITaskItem[] VSCoverageFiles
		{
			get;
			private set;
		}

        [Output]
        public ITaskItem[] EmmaFiles
		{
			get;
			private set;
		}

		[Output]
		public int Methods
		{
			get;
			private set;
		}

        public override bool Execute()
        {
			var assemblyName = this.GetType().Assembly.GetName();

			this.Log.LogMessage("Visual Studio Coverage file to Emma converter {0} (MSBuild)", assemblyName.Version);
			this.Log.LogMessage("Copyright (c) Kouji Matsui, All rights reserved.");

			var converterLoader = new VSConverterLoader();
			converterLoader.Exception += (s, e) =>
				{
					if (this.Verbose == true)
					{
						this.Log.LogErrorFromException(e.Exception, false, false, e.ModulePath);
					}
				};

			var converterFolderPath = Path.GetDirectoryName(this.GetType().Assembly.Location);
			converterLoader.Load(converterFolderPath);

			this.Log.LogMessage("  Available converters: {0}.", converterLoader.Join(", "));

			var vsCoverageFolderPath = VSCoverageFolderPath.ItemSpec;
			var binariesFolderPath = (this.BinariesFolderPath != null) ? Path.GetFullPath(this.BinariesFolderPath.ItemSpec) : vsCoverageFolderPath;
			var symbolsFolderPath = (this.SymbolsFolderPath != null) ? Path.GetFullPath(this.SymbolsFolderPath.ItemSpec) : binariesFolderPath;
			var emmaFolderPath = (this.EmmaFolderPath != null) ? Path.GetFullPath(this.EmmaFolderPath.ItemSpec) : vsCoverageFolderPath;

			var vsConverter = converterLoader.Create(this.ConverterName, binariesFolderPath, symbolsFolderPath);

			this.Log.LogMessage("Selected converter: {0}", vsConverter.Name);

			var vsCoverageFiles = new List<ITaskItem>();
			var emmaFiles = new List<ITaskItem>();

			var converter = new VSCoverageToEmmaConverter(vsConverter);
			converter.Converted += (sender, e) =>
			{
				lock (vsCoverageFiles)
				{
					vsCoverageFiles.Add(new TaskItem(e.CoveragePath));
					emmaFiles.Add(new TaskItem(e.EmmaPath));
				}

				this.Log.LogMessage(
					"VSCoverageToEmma: \"{0}\" --> \"{1}\" [{2} methods]",
					Path.GetFileName(e.CoveragePath),
					Path.GetFileName(e.EmmaPath),
					e.Methods);
			};

			var start = DateTime.Now;

			var methods = converter.ConvertCoverages(vsCoverageFolderPath, emmaFolderPath);

			this.Log.LogMessage("VSCoverageToEmma: Finished, found total {0} methods, processing {1} seconds.",
				methods,
				(DateTime.Now - start).TotalSeconds);

			this.VSCoverageFiles = vsCoverageFiles.ToArray();
			this.EmmaFiles = emmaFiles.ToArray();
			this.Methods = methods;

            return true;
        }
	}
}
